package com.logicbus.backend.websocket;

import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.doc.json.JsonObject;
import com.anysoft.util.Settings;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.*;
import java.io.IOException;
import java.util.HashMap;

/**
 * Websocket基础代码
 *
 * @since 1.6.14.1 [20210310 duanyy] <br>
 */
public abstract class WSEndpointBase2 {

    /**
     * a logger of slf4j
     */
    protected static final Logger LOG = LoggerFactory.getLogger(WSEndpointBase.class);
    protected static final String SESSIONID = "$session";

    protected boolean doOpen(Session session, EndpointConfig config){
        Logiclet onOpen = (Logiclet) session.getUserProperties().get("on-open");
        if (onOpen != null){
            LogicletContext logicletContext = new LogicletContext(
                    new SessionProperties(session, Settings.get()));
            try {
                logicletContext.setObject(SESSIONID,session);
                XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                onOpen.execute(doc,doc, logicletContext, null);
            }catch (Exception ex){
                LOG.info("Failed to execute on-open event" + ExceptionUtils.getStackTrace(ex));
            }finally {
                logicletContext.removeObject(SESSIONID);
            }
            return true;
        }
        return false;
    }

    public boolean doClose(Session session,CloseReason reason){
        Logiclet onClose = (Logiclet) session.getUserProperties().get("on-close");
        if (onClose != null){
            LogicletContext logicletContext = new LogicletContext(
                    new SessionProperties(session, Settings.get()));
            try {
                logicletContext.setObject(SESSIONID,session);
                logicletContext.SetValue("$status",String.valueOf(reason.getCloseCode().getCode()));
                logicletContext.SetValue("$reason",reason.getReasonPhrase());
                XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                onClose.execute(doc,doc, logicletContext, null);
            }catch (Exception ex){
                LOG.info("Failed to execute on-close event" + ExceptionUtils.getStackTrace(ex));
            }finally {
                logicletContext.removeObject(SESSIONID);
            }
            return true;
        }
        return false;
    }

    public boolean doText(Session session,String text)throws IOException {
        Logiclet onText = (Logiclet)session.getUserProperties().get("on-text");
        if (onText != null){
            LogicletContext logicletContext = new LogicletContext(
                    new SessionProperties(session, Settings.get()));
            try {
                logicletContext.setObject(SESSIONID,session);
                logicletContext.SetValue("$text",text);
                XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                onText.execute(doc,doc, logicletContext, null);
            }catch (Exception ex){
                LOG.info("Failed to execute on-text event" + ExceptionUtils.getStackTrace(ex));
            }finally {
                logicletContext.removeObject(SESSIONID);
            }
            return true;
        }
        return false;
    }

    public boolean doData(Session session, byte[] data)throws IOException{
        Logiclet onData = (Logiclet)session.getUserProperties().get("on-data");
        if (onData != null){
            LogicletContext logicletContext = new LogicletContext(
                    new SessionProperties(session, Settings.get()));
            try {
                logicletContext.setObject(SESSIONID,session);
                logicletContext.SetValue("$data", Base64.encodeBase64String(data));
                XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                onData.execute(doc,doc, logicletContext, null);
            }catch (Exception ex){
                LOG.info("Failed to execute on-data event" + ExceptionUtils.getStackTrace(ex));
            }finally {
                logicletContext.removeObject(SESSIONID);
            }
            return true;
        }
        return false;
    }

    public boolean doError(Session session,Throwable t){
        Logiclet onError = (Logiclet) session.getUserProperties().get("on-error");
        if (onError != null){
            LogicletContext logicletContext = new LogicletContext(
                    new SessionProperties(session, Settings.get()));
            try {
                logicletContext.setObject(SESSIONID,session);
                logicletContext.SetValue("$error",t.getMessage());
                logicletContext.SetValue("$error.stack",ExceptionUtils.getStackTrace(t));
                XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                onError.execute(doc,doc, logicletContext, null);
            }catch (Exception ex){
                LOG.info("Failed to execute on-close event" + ExceptionUtils.getStackTrace(ex));
            }finally {
                logicletContext.removeObject(SESSIONID);
            }
            return true;
        }
        return false;
    }
}
